#include "mainwindow.h"
#include <QFont>
#include <QPoint>
#include <QString>
#include <QPainter>
#include <QMessageBox>
#include <ctime>
#include <cmath>
//#include<iostream>
#include <QCursor>
#include <QMouseEvent>
#include <QApplication>
#include <QTimer>
#include<cstdlib>
#include<math.h>
#include<QElapsedTimer>
#include<QtCore/QCoreApplication>
#include<QtMultimedia/QMediaPlayer>
#include<QIcon>
#include<QBitmap>
#include<QProcess>
#include<QTime>
#include <QApplication>
#include <QMediaPlayer>
#include <QMediaPlaylist>
//#include "ui_mainwindow.h"

#define Move(BALL)\
QPoint p2=QPoint(BALL.x,BALL.y);\
QPixmap pix;\
switch (BALL.type) {\
case 0:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/1.pic.jpg");break;}\
case 1:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/2.pic.jpg");break;}\
case 2:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/3.pic.jpg");break;}\
case 3:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/4.pic.jpg");break;}\
case 4:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/5.jpg");break;}\
case 5:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/6.jpg");break;}\
case 6:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/7.jpg");break;}\
case 7:{pix.load(":/new/prefix1/res.qrc/skzphoto/pictures/8.pic.jpg");break;}\
}\
paint.drawPixmap(BALL.x-BALL.size,BALL.y-BALL.size,2*BALL.size,2*BALL.size,pix);\
//球移动过程中绘图
long long int time1;//扔球时间间隔
double K=0.25;//能量损失系数
const double speedlimit=50;
double X0,Y0;
const int HEIGHT=960;
const int WIDTH=540;
const int TOPLINE=100;
//状态status常量
const int CLEAR=2;
const int START=1;
const int STOP=0;
const int SHOW1=3;
const int BOOM=4;
const int Win=5;
const int Showrule=6;
const int Lose=7;
//定义不同的游戏状态
int gamescore=0;
QString str;
MainWindow::MainWindow(QWidget *parent)
    :QMainWindow(parent)
{
    setFixedSize(WIDTH,HEIGHT);//将窗口大小进行固定
    setWindowTitle("合成SKZ");
    initialUIC();//初始化界面
    iniSignals();//按钮与函数连接
    status=STOP;
    setMouseTracking(true);//开始鼠标移动
    startTimer(20);//启动计时器
    nextBall();//生成第一个球

    //设置背景色
    QPalette pal;
    pal.setColor(QPalette::Window,Qt::white);
    this->setAutoFillBackground(true);
    this->setPalette(pal);
    //计分
    q=new QLabel(this);
    str.asprintf("score:%d",gamescore);
    q->setText(str);
    q->setStyleSheet("color:white");
    q->resize(WIDTH,TOPLINE);
    QFont ft1;//字体
    ft1.setPointSize(40);
    q->move(0,5);
    q->setFont(ft1);
    q->hide();

    //初始化分数标签

}
MainWindow::~MainWindow()
{
    delete start;
    delete rank;
    delete exit;
    delete back;
    delete pause;
    delete finish;
    delete q;
    delete win;
    delete again;
}
//析构函数

void MainWindow::setbutton1(QPushButton*B,int width,int height,int x,int y,QString str)
{
    const int FSIZE=WIDTH/20;//按钮字体大小
    QFont font;
    font.setPointSize(FSIZE);
    font.setWeight(3);
    B->resize(width,height);
    B->setText(str);
    B->move(x,y);
    B->setFont(font);
}
void MainWindow::setbutton2(QPushButton*B,int width,int height,int x,int y,int a)
{
    B->move(x,y);
    if(a==1)
    {
        QPixmap pixmap1(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg");
        pixmap1=pixmap1.scaled(100,100,Qt::IgnoreAspectRatio);
        B->setMask(QBitmap(pixmap1.mask()));
        QIcon button_ico(":/new/prefix1/res.qrc/skzphoto/pictures/start.jpg");
        B->setIcon(button_ico);
        B->setFixedSize(pixmap1.size());
        B->setIconSize(QSize(140,140));
    }
    else if (a==2)//？
    {
        QPixmap pixmap2(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg");
        pixmap2=pixmap2.scaled(100,100,Qt::IgnoreAspectRatio);
        B->setMask(QBitmap(pixmap2.mask()));
        QIcon button_ico(":/new/prefix1/res.qrc/skzphoto/pictures/rules.jpg");
        B->setIcon(button_ico);
        B->setFixedSize(pixmap2.size());
        B->setIconSize(QSize(140,140));
    }
    else if(a==3)
    {
        QPixmap pixmap3(":/new/prefix1/res.qrc/skzphoto/pictures/arrow.jpg");
        pixmap3=pixmap3.scaled(100,100,Qt::IgnoreAspectRatio);
        B->setMask(QBitmap(pixmap3.mask()));
        QIcon button_ico(":/new/prefix1/res.qrc/skzphoto/pictures/arrow.jpg");
        B->setIcon(button_ico);
        B->setFixedSize(pixmap3.size());
        B->setIconSize(QSize(152,152));
    }
}
void MainWindow::restart()
{
    qApp->quit();
    QProcess::startDetached(qApp->applicationFilePath(),QStringList());
}
void MainWindow::initialUIC()
{
    //按钮宽和高
    const int BWIDTH=WIDTH/3;
    const int BHEIGHT=HEIGHT/9;
    //按钮初始化
    start=new QPushButton(this);
    win=new QPushButton(this);
    rank=new QPushButton(this);
    exit=new QPushButton(this);
    back=new QPushButton(this);
    pause=new QPushButton(this);
    finish=new QPushButton(this);
    again=new QPushButton(this);
    setbutton2(start,BWIDTH,BHEIGHT,72,BHEIGHT*6.75,1);
    setbutton2(rank,BWIDTH,BHEIGHT,212,BHEIGHT*6.75,2);
    setbutton2(exit,BWIDTH,BHEIGHT,374,BHEIGHT*6.75,3);
    setbutton2(back,BWIDTH,BHEIGHT,BWIDTH*1.2,BHEIGHT*7,4);
    setbutton1(pause,40,40,WIDTH-45,5,"||");
    setbutton2(finish,BWIDTH,BHEIGHT*2,220,BHEIGHT*4,5);
    setbutton2(win,500,250,220,BHEIGHT*4,6);
    setbutton2(again,BWIDTH,BHEIGHT,146,BHEIGHT*4.59,1);
    //隐藏“back ”“pause”
    back->hide();
    pause->hide();
    finish->hide();
    win->hide();
    again->hide();
}
void MainWindow::StartGame()
{
    status=Win;
    update();
    q->show();
    status=CLEAR;//清屏
    update();
    status=START;//游戏状态初始为start
    showbuttons(false);//隐藏初始界面的按钮
    pause->show();//显示暂停按钮
    pause->raise();//上层显示
    win->show();

}
void MainWindow::showrule()
{
    status=Showrule;
    QPainter p(this);
    p.drawPixmap(0,0,WIDTH,HEIGHT,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/showrules.jpg"));
    showbuttons(false);
    back->show();
}
void MainWindow::backgame()
{

}
void MainWindow::pausegame()
{

}
void MainWindow::restartgame()
{
    status=CLEAR;//清屏
    update();
    showbuttons(true);
    pause->hide();
    status=STOP;//停止游戏
    restart();
}
void MainWindow::showbuttons(bool)
{

}
void MainWindow::finishgame()
{
    status=Lose;
    restart();
}
void MainWindow::wingame()
{
    status=Win;
    restart();
}
void MainWindow::iniSignals()
{
    connect(start, &QPushButton::clicked, this, &MainWindow::StartGame);

}
void MainWindow::nextBall()
{
    //随机生成下一个球的种类
    srand((unsigned)time(NULL));
    unfalling.type=rand()%5;
    //种类设置大小质量和颜色
    unfalling.initial_ball(unfalling.type);
    int x1;
    //判断生成的球是否出界，并设置其坐标
    if(mouse.x()<unfalling.size)x1=unfalling.size;
    else if(mouse.x()>WIDTH-unfalling.size)x1=WIDTH-unfalling.size;
    else x1=mouse.x();
    unfalling.x=unfalling.x0=x1;
    unfalling.y=unfalling.y0=5+unfalling.size;
}
void MainWindow::repaintEvent(QPaintEvent *event)
{
    if(status==STOP)
    {
        QPainter p(this);
        p.drawPixmap(0,0,WIDTH,HEIGHT,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg"));
    }
    if (status==START)
    {
        QPainter paint(this);
        paint.drawPixmap(0,0,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg"));
        //清屏
        paint.drawPixmap(-100,TOPLINE-40,QPixmap(":/pictures/line.jpg"));//?
        paint.setRenderHint(QPainter::Antialiasing);
        Move(unfalling)//调用宏移动未掉落的球
            for(int i=0;i<int(balls.size());i++ )
        {
            Move(balls[i]);
        }
    }
    else if(status==CLEAR)//清屏
    {
        QPainter paint(this);
        paint.setBrush(QBrush(Qt::white,Qt::SolidPattern));
        paint.drawRect(QRect(0,0,WIDTH,HEIGHT));
        paint.drawPixmap(0,0,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg"));

    }
    else if(status==SHOW1)
    {
        QPainter paint(this);
        paint.drawPixmap(0,0,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg"));
    }
    else if(status==BOOM)
    {
        QPainter paint(this);
        paint.drawPixmap(int(X0),int(Y0),QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/beijing.jpg"));
    }//这块好多nankai的图片全写的背景 前面好像还有
    else if(status==Showrule)
    {
        QPainter paint (this);
        paint.drawPixmap(-80,-80,QPixmap(":/new/prefix1/res.qrc/skzphoto/pictures/showrules.jpg"));
    }
    else if(status==Win)
    {
        QPainter paint(this);
        QPixmap  pix(":/new/prefix1/res.qrc/skzphoto/pictures/win.jpg");
        pix.scaled(500,500);
        paint.drawPixmap(0,0,pix);
        QMediaPlayer *winmusic=new QMediaPlayer(this);
        winmusic->setMedia(QUrl("qrc:/win.mp3"));
        winmusic->setVolume(50);
        winmusic->play();
        back->show();
    }//音乐还没加进来
    else if(status==Lose)
    {
        QPainter paint (this);
        QPixmap pix(":/new/prefix1/res.qrc/skzphoto/pictures/lose.jpg");
        pix.scaled(500,500);
        paint.drawPixmap(0,0,pix);
        back->show();
    }
}
void MainWindow::removemouseEvent(QMouseEvent *event)
{
    if (status==START)
    {
        mouse=event->pos();
        if(mouse.x()<unfalling.size||mouse.x()>WIDTH-unfalling.size)return;//鼠标出界
        //鼠标出界将边界作为球的坐标
        int x1;
        if(mouse.x()<unfalling.size)x1=unfalling.size;
        else if(mouse.x()>WIDTH-unfalling.size) x1=WIDTH-unfalling.size;
        else x1=mouse.x();
        //更新未下落的球的坐标和鼠标的坐标
        unfalling.x=x1;
        mouse=event->pos();
        int rannum=rand()%7;
        unfalling.x+=rannum;
        update();
    }
}
void MainWindow::repressmouseEvent(QMouseEvent *event)
{
      // 保存鼠标事件的位置
        QPoint clickPosition = event->pos();

        // 使用QTimer来延迟执行点击操作，以便在原始事件处理完毕后进行
        QTimer::singleShot(0, [this, clickPosition]() {
            // 将鼠标移动到指定位置
            QCursor::setPos(clickPosition);

            // 模拟鼠标左键按下和释放事件
            QMouseEvent pressEvent(QEvent::MouseButtonPress, clickPosition, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
            QMouseEvent releaseEvent(QEvent::MouseButtonRelease, clickPosition, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

            QApplication::postEvent(this, &pressEvent);
            QApplication::postEvent(this, &releaseEvent);
        });

}
void MainWindow::retimeEvent(QTimerEvent *event)
{
    if(status==STOP) return;
    if(clock()-time1>CLOCKS_PER_SEC&&&time!=0)
    {
        time1=0;
        winorlose();//判断是否游戏失败
        nextBall();
    }
    change();
    update();
}
void MainWindow::winorlose()
{
    for(int j=0;j<balls.size();j++)
    {
        if(balls[j].y-balls[j].size<=TOPLINE)//是否越界
        {
            for(int i=0;i<balls.size();i++)
            {
                gamescore+=balls[i].type*2;
            }
            status==Lose;
            back->show();
        }
    }
}
void MainWindow::change()
{
    for(int i=0;i<int(balls.size());i++)
    {
        balls[i].vx+=balls[i].ax;
        balls[i].vy+=balls[i].ay;
        balls[i].x0+=balls[i].x;
        balls[i].y0+=balls[i].y;
        balls[i].x+=balls[i].vx-0.5*balls[i].ax;
        balls[i].y+=balls[i].vy-0.5*balls[i].ay;
        collideWall(i);
    }
    collision();
    for(int i=0;i<int(balls.size());i++)collideWall(i);
    for(int i=0;i<int(balls.size());i++)
    {
        if(balls[i].type==8)
        {
            QTime time;
            time.start();
            while(time.elapsed()<2000)//等待时间流逝两秒钟

                QCoreApplication::processEvents();

            status=Win;
        }
    }
}
void MainWindow::collideWall(int i)
{
    if(balls[i].x>=WIDTH-balls[i].size)
    {
        balls[i].x=WIDTH-balls[i].size;//防止速度过快穿墙
        balls[i].vx=-balls[i].vx*0.5;
    }//撞右边的墙
    if(balls[i].x<=balls[i].size)
    {
        balls[i].x=balls[i].size;
        balls[i].vx=-balls[i].vx*0.5;
    }//撞左边的墙
    if(balls[i].y>=HEIGHT-balls[i].size)
    {
        balls[i].y=HEIGHT-balls[i].size;
        balls[i].vy=-balls[i].vy*0.5;
    }
    else if(balls[i].y>TOPLINE+balls[i].size)balls[i].falling=1;

    if(balls[i].y==HEIGHT-balls[i].size)//设置摩擦
    {
        if(balls[i].vx<balls[i].ax)
            balls[i].vx=0;
        if(balls[i].vx!=0)
        {
            if(balls[i].vx<0)balls[i].ax=0.05;//向右摩擦力
            if(balls[i].vx>0)balls[i].ax=-0.05;
        }
    }
    else if(balls[i].y<HEIGHT-balls[i].size)//x加速度置为0
    {
        balls[i].ax=0;
    }
}
void MainWindow::collision()
{
    for(int i=0;i<int(balls.size());i++)
    {
        for(int j=0;j<int(balls.size());j++)
        {
            double dx=balls[i].x-balls[j].x;
            double dy=balls[i].y-balls[j].y;
            double distance=sqrt(dx*dx+dy*dy);
            double D=balls[i].size+balls[j].size;
            if(distance>D) continue;
            //两种球种类相同则合成
           /* if(balls[i].vx>=20||balls[i].vy>=20||balls[j].vx>=20||balls[j].vy>=20)
            {

            }*/
            if(balls[i].type==balls[j].type)
            {
                if(i==1)
                {
                    QMediaPlayer *crush1=new QMediaPlayer(this);
                    crush1->setMedia(QUrl("qrc:/1.mp3"));
                    crush1->setVolume(50);
                    crush1->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==2)
                {
                    QMediaPlayer *crush2=new QMediaPlayer(this);
                    crush2->setMedia(QUrl("qrc:/2.mp3"));
                    crush2->setVolume(50);
                    crush2->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==3)
                {
                    QMediaPlayer *crush3=new QMediaPlayer(this);
                    crush3->setMedia(QUrl("qrc:/3.mp3"));
                    crush3->setVolume(50);
                    crush3->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==4)
                {
                    QMediaPlayer *crush4=new QMediaPlayer(this);
                    crush4->setMedia(QUrl("qrc:/4.mp3"));
                    crush4->setVolume(50);
                    crush4->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==5)
                {
                    QMediaPlayer *crush5=new QMediaPlayer(this);
                    crush5->setMedia(QUrl("qrc:/5.mp3"));
                    crush5->setVolume(50);
                    crush5->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==6)
                {
                    QMediaPlayer *crush6=new QMediaPlayer(this);
                    crush6->setMedia(QUrl("qrc:/6.mp3"));
                    crush6->setVolume(50);
                    crush6->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==7)
                {
                    QMediaPlayer *crush7=new QMediaPlayer(this);
                    crush7->setMedia(QUrl("qrc:/7.mp3"));
                    crush7->setVolume(50);
                    crush7->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }
                if(i==8)
                {
                    QMediaPlayer *crush8=new QMediaPlayer(this);
                    crush8->setMedia(QUrl("qrc:/8.mp3"));
                    crush8->setVolume(50);
                    crush8->play();
                    combine(i,j);
                    X0=balls[i].x;
                    Y0=balls[i].y;
                    status=BOOM;
                    update();
                    status=START;
                    continue;
                }

            }
            double vi=sqrt(balls[i].vx*balls[i].vx+balls[i].vy*balls[i].vy);
            double vj=sqrt(balls[j].vx*balls[j].vx+balls[j].vy*balls[j].vy);
            if(vi>speedlimit||vj>speedlimit)//速度过快，强制沿着原方向退回一段距离
            {
                double dxi=(balls[i].x0-balls[i].x)/10.0;
                double dyi=(balls[i].y0-balls[i].y)/10.0;
                double dxj=(balls[j].x0-balls[j].x)/10.0;
                double dyj=(balls[j].y0-balls[j].y)/10.0;
                for(int k=0;k<10&&distance-D<0;k++)
                {
                    balls[i].x+=dxi;
                    balls[i].y+=dyi;
                    balls[j].x+=dxj;
                    balls[j].y+=dyj;
                    dx=balls[i].x-balls[j].x;
                    dy=balls[i].y-balls[j].y;
                    distance=sqrt(dx*dx+dy*dy+0.0);
                }
            }
            double ex=dx/distance,ey=dy/distance;//法向单位向量（ex,ey),方向由j指向i
            if(distance<D)//对重叠在一起的球进行位置的修正
            {
                double dd=D-distance;
                balls[j].x-=dd*ex*balls[i].m/(balls[i].m+balls[j].m);
                balls[i].x+=dd*ex*balls[j].m/(balls[i].m+balls[j].m);
                if(balls[i].y>balls[j].y)
                {
                    balls[j].y-=fabs(dd*ey);
                }
                else balls[i].y-=fabs(dd*ey);
            }
            double ux=-dy/distance,uy=dx/distance;//切向单位向量（ux,uy),方向为（ex,ey)逆时针旋转二分之拍
            //球在两球连线方向上的速度投影为v=(vx,vy)·(ex,ey)
            double v1=ex*balls[i].vx+ey*balls[i].vy;//i的法向速度
            double v2=ex*balls[j].vx+ey*balls[j].vy;//j的法向速度
            if(v2<v1)continue;//不相撞
            //球在切线方向的速度投影为v'=(vx,vy)*(ux,uy)
            double v11=ux*balls[i].vx+uy*balls[i].vy;//i的切向速度
            double v22=ux*balls[j].vx+uy*balls[j].vy;//i的切向速度
            //根据动量守恒和动能定理来计算碰撞后两球连线方向上的速度u1,u2。其中K表示动能损失程度
            double m1=balls[i].m,m2=balls[j].m;
            double u1=K*((m1-m2)*v1+2*m2*v2)/(m1+m2);//i碰撞后法向速度
            double u2=K*((m2-m1)*v2+2*m1*v1)/(m1+m2);//j碰撞后法向速度
            //最终的速度矢量（vx,vy)=(u1*ex+v11*ux,u1*ey+v11*uy)*(i,j)
            balls[i].vx=1*(u1*ex+v11*ux);
            balls[i].vy=1*(u1*ey+v11*uy);
            balls[j].vx=1*(u2*ex+v22*ux);
            balls[j].vy=1*(u2*ey+v22*uy);
        }
    }
}
void MainWindow::combine(int i,int j)
{
    BALL b;
    b.initial_ball(balls[i].type+1);
    double vi=sqrt(balls[i].vx*balls[i].vx+balls[i].vy*balls[i].vy);
    double vj=sqrt(balls[j].vx*balls[j].vx+balls[j].vy*balls[j].vy);
    if(vi<vj)//合成的位置为速度较小的球
    {
        b.x=b.x0=balls[i].x;
        b.y=b.y0=balls[i].y;
    }
    else
    {
        b.x=b.x0=balls[j].x;
        b.y=b.y0=balls[j].y;
    }
    b.vx=(balls[i].vx+balls[j].vx)/2.0;
    b.vy=(balls[i].vy+balls[j].vy)/2.0;
    b.ay=1;
    b.falling=1;
    balls[i]=b;//将新合成的球替换balls[i]
    collideWall(i);
    balls[j]=balls[balls.size()-1];
    balls.pop_back();
    gamescore+=2*balls[i].type;
    str.asprintf("score:%d",gamescore);
    q->setText(str);

}
